/**
   Event system for the LOM engine.  It is important that a client
   listening to this system would be able to figure out exactly what
   is going on.
*/

#ifndef LOMEVENTSHH
#define LOMEVENTSHH
#include "lom-typedefs.hh"

namespace lom
{
    //Users should be able to provide this class
    
    class LomClass;
    class LomValue;

    class ILomEventHandler
    {
    public:
	virtual ~ILomEventHandler(){}
	virtual void event( licada::TNameType name, const TValueVector& args ) = 0;
	virtual void classCreated( const LomClass& cls ) = 0;
	virtual void instanceCreated( THandle instance ) = 0;
	virtual void instanceDestroyed( THandle instance ) = 0;
	virtual void propertyEvent( THandle instance
				    , licada::uint32 propIndex
				    , const LomValue& finalValue ) = 0;
	/**
	   The lom system defines a root context with a set of
	   key-value pairs.  When something changes the root context,
	   this event is sent.
	 */
	virtual void rootObjectSet( licada::TNameType name, const LomValue& value ) = 0;	
    };
    
    class ILomEventSystem : public ILomEventHandler
    {
    public:
	virtual ~ILomEventSystem(){}
	virtual void addEventHandler( ILomEventHandler* system ) = 0;
        virtual void removeEventHandler( ILomEventHandler* system ) = 0;
    };

    class EventSender
    {
    protected:
	mutable ILomEventHandler* eventSystem;
    public:
	EventSender();
	virtual ~EventSender();
	void setEventHandler( ILomEventHandler* evt ) const;
	ILomEventHandler* getEventHandler() const;
	
	//Simply forwards the calls to child systems
	virtual void sendClassCreated( const LomClass& cls );
	virtual void sendInstanceCreated( THandle instance );
	virtual void sendInstanceDestroyed( THandle instance );
	virtual void sendPropertyEvent( THandle instance
					, licada::uint32 propIndex
					, const LomValue& finalValue );
    };
    

    //Forwards events to different systems
    class LomEventSystem : public ILomEventSystem
    {
	TEventHandlerVector eventSystems;
	
    public:
	virtual ~LomEventSystem();
	
	virtual void addEventHandler( ILomEventHandler* system );
        virtual void removeEventHandler( ILomEventHandler* system );
	virtual void reset() { eventSystems.clear(); }
	virtual const TEventHandlerVector& getEventSystems() { return eventSystems; }

	//Simply forwards the calls to child systems
	virtual void event( licada::TNameType name, const TValueVector& args );
	virtual void classCreated( const LomClass& cls );
	virtual void instanceCreated( THandle instance );
	virtual void instanceDestroyed( THandle instance );
	virtual void propertyEvent( THandle instance
				    , licada::uint32 propIndex 
				    , const LomValue& finalValue );
	virtual void rootObjectSet( licada::TNameType name, const LomValue& value );
    };
}

#endif
